const defaultOptions = {
  limit: 1920 //宽高限制
}

/**
 * 图片裁剪
 *
 * @class scale
 */
class Scale {
  constructor(file, options) {
    if (!file) {
      throw new error("no file")
    }
    this.options = Object.assign({}, defaultOptions, options)
    this.file = file
    this.filename = file.name
    this.filetype = file.type
  }

  /**
   * 根据宽高的最大限制将File对象缩放,并返回FormData
   *
   * @returns {FormData}
   * @memberof scale
   */
  async fileToFormdata(formDataName = "filecontent") {
    let dataUrl = await this.readFile(this.file)
    const size = await this.getImageSize(dataUrl)
    let limit = this.options.limit

    if (size.width > limit || size.height > limit) {
      let ratio =
        limit / size.width < limit / size.height
          ? limit / size.width
          : limit / size.height
      this.scaledFile = await this.scaleImage(size.image, ratio)
      // this.scaledFile = new File([blob], this.filename, {
      //   type: this.filetype
      // })
    } else {
      this.scaledFile = this.file
    }
    let formData = new FormData()
    formData.append(formDataName, this.scaledFile, this.filename)
    return formData
  }

  /**
   * 计算dataUrl格式图片的宽高
   *
   * @param {data URL} dataUrl
   * @returns {Object} 返回包含宽高和对应dom对象的对象
   * @memberof scale
   */
  getImageSize(dataUrl) {
    return new Promise((resolve, reject) => {
      const img = new Image()
      img.src = dataUrl
      img.onload = function() {
        let width = img.naturalWidth
        let height = img.naturalHeight
        resolve({
          width: width,
          height: height,
          image: img
        })
      }
    })
  }

  /**
   * 异步读取文件对象，返回dataUrl
   *
   * @param {File} file
   * @returns {Data Url}
   * @memberof scale
   */
  readFile(file) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader()
      reader.onload = function() {
        resolve(reader.result)
      }
      reader.readAsDataURL(file)
    })
  }

  /**
   * 根据比例对dom对象的图片进行缩放，并返回blob对象
   *
   * @param {Dom} img image对象
   * @param {Number} ratio 比例
   * @returns {Blob}
   * @memberof scale
   */
  async scaleImage(img, ratio) {
    const canvas = document.createElement("CANVAS")
    const context = canvas.getContext("2d")
    canvas.width = img.width * ratio
    canvas.height = img.height * ratio
    context.drawImage(img, 0, 0, canvas.width, canvas.height)
    let blob = await this.canvasToBlob(canvas)
    return blob
  }

  /**
   * canvas转blob
   *
   * @param {any} canvas
   * @memberof Scale
   */
  canvasToBlob(canvas) {
    return new Promise((resolve, reject) => {
      canvas.toBlob(blob => resolve(blob), this.filetype)
    })
  }

  /**
   * 将data Url 转为 blob
   *
   * @param {any} dataurl
   * @returns {Blob}
   * @memberof scale
   */
  dataURLtoBlob(dataurl) {
    var arr = dataurl.split(","),
      mime = arr[0].match(/:(.*?);/)[1],
      bstr = atob(arr[1]),
      n = bstr.length,
      u8arr = new Uint8Array(n)
    while (n--) {
      u8arr[n] = bstr.charCodeAt(n)
    }
    return new Blob([u8arr], { type: mime })
  }
}

export default Scale
